package com.qsl.redisson;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.redisson.Redisson;
import org.redisson.api.RBucket;
import org.redisson.api.RList;
import org.redisson.api.RLock;
import org.redisson.api.RMap;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RSet;
import org.redisson.api.RSortedSet;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * @author 青石路
 * @date 2021/4/9 14:38
 */
public class RedissonTest {

    private RedissonClient redissonClient;

    /**
     * https://github.com/redisson/redisson/wiki/2.-Configuration
     * 配置redis服务器信息，创建出 redissonClient
     * 配置模式有很多：
     *      Cluster mode
     *      Replicated mode
     *      Single instance mode
     *      Sentinel mode
     *      Master slave mode
     *      Proxy mode
     */
    @Before
    public void before() {
        Config config = new Config();
        config.useSingleServer()
                .setAddress("redis://192.168.1.110:6379");
        redissonClient = Redisson.create(config);
    }

    @After
    public void after() {
        redissonClient.shutdown();
    }

    /**
     * 限流
     */
    @Test
    public void rateLimiter() {

        RRateLimiter limiter = redissonClient.getRateLimiter("myLimiter");
        // Initialization required only once.
        // 5 permits per 2 seconds
        limiter.trySetRate(RateType.OVERALL, 5, 2, RateIntervalUnit.SECONDS);

        // acquire 3 permits or block until they became available
        limiter.acquire(3);
    }

    /**
     * redis 5 大数据类型的基本操作
     */
    @Test
    public void baseOperate() {
        RBucket<String> bucket = redissonClient.getBucket("name");
        String name = bucket.get();
        System.out.println("name = " + name);
        bucket.set("123");
        name = bucket.get();
        System.out.println("name = " + name);

        RList<Object> list = redissonClient.getList("list");
        RSet<Object> set = redissonClient.getSet("set");
        RSortedSet<Object> sortedSet = redissonClient.getSortedSet("sortedSet");
        RMap<Object, Object> map = redissonClient.getMap("person");
        Object age = map.get("age");
        System.out.println("age = " + age);
        map.put("age", 21);
        age = map.get("age");
        System.out.println("age = " + age);
    }

    /**
     * 单线程
     */
    @Test
    public void simpleLock() {
        RLock testLock = redissonClient.getLock("simple_lock");
        try {
            testLock.lock();
            System.out.println("simple test...");
        } finally {
            testLock.unlock();
        }
    }

    /**
     * 多线程
     * @throws Exception
     */
    @Test
    public void multiLock() throws Exception {

        RLock testLock = redissonClient.getLock("multi_lock");
        int count = 5;
        CountDownLatch latch = new CountDownLatch(count);

        for (int i=1; i<=count; i++) {
            new Thread(() -> {
                try {
                    System.out.println("线程 " + Thread.currentThread().getName() + " 尝试获取锁");
                    testLock.lock();
                    System.out.println(String.format("线程 %s 获取到锁, 执行业务中...", Thread.currentThread().getName()));
                    try {
                        TimeUnit.SECONDS.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(String.format("线程 %s 业务执行完成", Thread.currentThread().getName()));
                    latch.countDown();
                } finally {
                    testLock.unlock();
                    System.out.println(String.format("线程 %s 释放锁完成", Thread.currentThread().getName()));
                }
            }, "t" + i).start();
        }

        latch.await();
        System.out.println("结束");
    }
}
